from django.shortcuts import render, redirect

from django.http import HttpResponse

from django.views.generic import View

from django.core.urlresolvers import reverse

import re

from users.models import User, Address

from django import db

from celery_tasks.tasks import send_active_email

from django.conf import settings

from itsdangerous import TimedJSONWebSignatureSerializer as Serializer

from itsdangerous import SignatureExpired

from django.contrib.auth import authenticate, login, logout

# from django.contrib.auth.decorators import login_required

from utils.views import LoginRequiredMinix

from django_redis import get_redis_connection

from goods.models import GoodsSKU

import json
# Create your views here.


'''个人信息实现'''
class UserInfoView(LoginRequiredMinix, View):

    '''只有get获取页面'''
    def get(self, request):

        '''基本信息'''
        user = request.user

        try:
            address = user.address_set.latest('create_time')

        except Address.DoesNotExist:

            address = None

        '''假设已经存储了浏览记录的sku_id'''
        # 创建redis链接对象
        redis_connection = get_redis_connection('default')

        # 从redis取出前5个元素
        sku_ids = redis_connection.lrange('history_%s' % user.id, 0, 4)

        sku_list = []
        for sku_id in sku_ids:

            sku = GoodsSKU.objects.get(id=sku_id)

            sku_list.append(sku)


        context = {

            'address': address,

            'sku_list': sku_list
        }


        return render(request, 'user_center_info.html', context)




'''用户中心 --- 地址'''
# class LoginRequired(object):
#
#     @classmethod
#     def as_view(cls, **initkwargs):
#
#         view = super().as_view(**initkwargs)
#
#         return login_required(view)




class AddressView(LoginRequiredMinix, View):

    def get(self, request):

        user = request.user

        try:
            address = user.address_set.latest('create_time')

        except Address.DoesNotExist:

            address = None


        context = {

            'address': address
        }

        return render(request, 'user_center_site.html', context)

        # 只允许登录的用户查看
        # if request.user.is_authenticated():
        #
        #     return render(request, 'user_center_site.html')
        #
        # else:
        #
        #     return redirect(reverse('users:login'))

    def post(self, request):
        '''编辑地址的表单提交'''

        '''获取参数'''
        recv_name = request.POST.get('recv_name')
        addr = request.POST.get('addr')
        zip_code = request.POST.get('zip_code')
        recv_mobile = request.POST.get('recv_mobile')


        '''参数校验'''
        if all([recv_name, addr, zip_code, recv_mobile]):

            '''保存用户地址'''
            Address.objects.create(

                user = request.user,
                receiver_name = recv_name,
                detail_addr = addr,
                zip_code = zip_code,
                receiver_mobile = recv_mobile
            )

        return redirect(reverse('users:address'))



'''退出登陆'''
class LogoutView(View):

    def get(self, request):

        logout(request)

        # return redirect(reverse('users:login'))
        return redirect(reverse('goods:index'))



'''登陆'''
class LoginView(View):

    def get(self, request):

        return render(request, 'login.html')

    def post(self, request):

        '''获取用户名和密码'''
        user_name = request.POST.get('username')

        password = request.POST.get('pwd')

        '''参数校验'''
        if not all([user_name, password]):

            return redirect(reverse('users:login'))

        '''django用户认证系统判断是否登陆成功'''
        user = authenticate(username = user_name, password = password)

        '''验证登陆失败'''
        if user is None:

            return render(request, 'login.html', {'errmsg':'用户名或密码错误'})

        '''判断用户是否激活'''
        if user.is_active is False:

            return render(request, 'login.html', {'errmsg':'用户名未激活'})

        '''在session中保存状态'''

        login(request, user)


        '''勾选记住用户名'''
        remembered = request.POST.get('remembered')


        '''是否勾选'''
        if remembered != 'on':

            # 不需要记住cookie
            request.session.set_expiry(0)

        else:
            # 需要记住c ookie信息， 默认为14天
            request.session.set_expiry(None)


        '''登陆时购物车中cookie合并到redis'''
        # 获取cookie数据/
        cart_json = request.COOKIES.get('cart')

        if cart_json is not None:
            cart_dict_cookie = json.loads(cart_json)
        else:
            cart_dict_cookie = {}

        # 从redis中获取数据
        redis_conn = get_redis_connection('default')

        cart_dict_redis = redis_conn.hgetall('cart_%s' % user.id)

        # 进行合并: redis中的是bytes类型, cookie中的sku_id是string类型
        for sku_id, count in cart_dict_cookie.items():

            # 将sku_id由string转化为bytes
            sku_id = sku_id.encode()

            # 如果redis中有相同的商品,就累加; 没有就重新赋值
            if sku_id in cart_dict_redis:
                # redis中的数量
                origin_count = cart_dict_redis[sku_id]

                count += int(origin_count)

            cart_dict_redis[sku_id] = count

        # 合并后保存到redis中: redis_conn.hmset()不能传入空字典
        if cart_dict_redis:
            redis_conn.hmset('cart_%s' % user.id, cart_dict_redis)


        # 登陆成功后地址变为http://127.0.0.1:8000/users/login?next=/users/address
        # 登陆成功后，根据next参数决定跳转方向
        # next位于？后，所以用GET方法获取:需要判断是跳转到主页还是next参数指向的页面
        next = request.GET.get('next')

        if next is None:

            # 登陆成功后就跳转至首页
            '''登陆成功重定向到主页'''
            response = redirect(reverse('goods:index'))
        else:
            # PlaceOrdereView支持POST请求，但是next参数重定向回来的是GET请求
            # 错误码: 405
            if next == '/orders/place':
                response = redirect('cart:info')

            else:
            # 重定向至next后的路径
                response = redirect(next)


        '''清楚cookie'''
        response.delete_cookie('cart')

        return response





'''邮件激活链接'''
class ActiveView(View):



    def get(self, request, token):
        # 创建序列化器
        serializer = Serializer(settings.SECRET_KEY, 3600)

        try:
            # 使用序列化器，获取token明文信息,需要判断签名是否过期
            result = serializer.loads(token)

        except SignatureExpired:
            # 提示激活链接已过期
            return HttpResponse('激活链接已过期')

        # 获取用户id
        user_id = result.get('confirm')

        try:
            # 查询需要激活的用户,需要判断查询的用户是否存在
            user = User.objects.get(id=user_id)

        except User.DoesNotExist:
            # 提示用户不存在
            return HttpResponse('用户不存在')

        # 设置激活用户的is_active为Ture
        user.is_active = True
        # 保存数据到数据库
        user.save()

        # 响应信息给客户端
        return redirect(reverse('users:login'))





'''类视图'''
class RegisterView(View):

    def get(self, request):
        return render(request, 'register.html')


    def post(self, request):

        # 处理POST请求，实现注册逻辑


        '''获取请求参数'''
        user_name = request.POST.get('user_name')

        password = request.POST.get('pwd')

        email = request.POST.get('email')

        allow = request.POST.get('allow')


        '''判断是否为空'''

        if not all([user_name, password, email]):

            return redirect(reverse('user；register'))

        '''判断邮箱格式'''

        if not re.match(r'^^[a-z0-9][\w\.\-]*@[a-z0-9\-]+(\.[a-z]{2,5}){1,2}$', email):

            return render(request, 'register.html', {'errmsg':'邮箱格式不正确'})


        '''判断是否勾选'''
        if allow != 'on':

            return render(request, 'register.html', {'errmsg': '没有勾选用户协议'})

        '''保存请求参数'''

        try:

            user = User.objects.create_user(user_name, email, password)

        except db.IntegrityError:

            return render(request, 'register.html', {'errmsg': '用户已注册'})


        '''重制激活状态'''
        user.is_active = False

        user.save()


        '''生成token'''
        token = user.generate_active_token()

        print(token)

        '''发送邮件'''

        send_active_email.delay(email, user_name, token)

        # def send_active_email(email, user_name, token):
        #     """封装发送邮件方法"""
        #     subject = "天天生鲜用户激活"  # 标题
        #     body = ""  # 文本邮件体
        #     sender = settings.EMAIL_FROM  # 发件人
        #     receiver = [email]  # 接收人
        #     html_body = '<h1>尊敬的用户 %s, 感谢您注册天天生鲜！</h1>' \
        #                 '<br/><p>请点击此链接激活您的帐号<a href="http://127.0.0.1:8000/users/active/%s">' \
        #                 'http://127.0.0.1:8000/users/active/%s</a></p>' % (user_name, token, token)
        #     send_mail(subject, body, sender, receiver, html_message=html_body)




        return HttpResponse('这里实现注册逻辑')









# def register(request):
#     """处理注册"""
#     # 函数视图
#     # 在一个视图中处理多种逻辑时，前提条件是多种逻辑的请求地址相同
#
#     # 获取请求方法，判断是GET/POST请求
#     if request.method == 'GET':
#         # 处理GET请求，返回注册页面
#         return render(request, 'register.html')
#     else:
#         # 处理POST请求，实现注册逻辑
#         return HttpResponse('这里实现注册逻辑')